#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <atomic>
#include <iostream>
#include <string>
#include <thread>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

namespace udp
{

const std::string fifo = "message_pipe";

class udp_client
{
public:
    udp_client(const std::string& sip, uint16_t sport)
        : _sock(0)
        , _fifo_fd(0)
        , _sip(sip)
        , _sport(sport)
    {
        
		WSAData wsd;
		//启动Winsock
		//进行Winsocket的初始化，windows初始化socket网络库，申请2.2的版本
		if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
		{
			std::cout << "WSAStartup Error =" << WSAGetLastError() << std::endl;
            exit(1);
		}
		std::cout << "WSAStartup Success" << std::endl;

        _sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sock < 0)
        {
            std::cerr << "socket error" << std::endl;
            exit(2);
        }
        std::cout << "socket success " << _sock << std::endl;

        // 客户端不需要手动绑定

		_sender = std::thread(&udp_client::send, this);
        _recver = std::thread(&udp_client::recv, this);
    }

    ~udp_client()
    {
        _sender.join();
        _recver.join();

        //最后将使用库的相关资源全部释放掉 关闭套接字的文件描述符
		closesocket(_sock);
		WSACleanup();
    }

    void send()
    {
        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr(_sip.c_str());
        server.sin_port = htons(_sport);

        while (true)
        {
            std::string msg;
            std::cerr << "please input:> ";
            getline(std::cin, msg);
            sendto(_sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&server, sizeof(server));
        }
    }

    void recv()
    {
        while (true)
        {
            struct sockaddr_in tmp;
            int len = sizeof(tmp);
            char buf[1024] = {0};
            int s = recvfrom(_sock, buf, sizeof(buf), 0, (struct sockaddr*)&tmp, &len);

            if (s > 0) buf[s] = 0;
            else continue;
            // std::cout << "server echo# " << buf << std::endl;
            std::cout << buf << std::endl;
        }
    }

private:
    SOCKET _sock;
    int _fifo_fd;
    std::string _sip;
    uint16_t _sport;

    std::thread _sender;
    std::thread _recver;
};

}
